#pragma once
#include <istream>
#include <ostream>
#include <string>
#include <boost/noncopyable.hpp>
#include "../inc_boost_io_ios_state.hpp"

namespace wxx {
namespace detail
{
#define WXX_ENUM_FORMATTER_BEGIN(Enum)                                     \
		template<class Ch, class Tr>                                       \
		std::basic_ostream<Ch, Tr>&                                        \
		operator<< (std::basic_ostream<Ch, Tr>& output, const Enum value)  \
		{                                                                  \

#define WXX_ENUM_FORMATTER(VALUE, NAME)                                    \
			if (value == VALUE)                                            \
			{                                                              \
				output << NAME;                                            \
				return output;                                             \
			}

#define WXX_ENUM_FORMATTER_END                                             \
			return output;                                                 \
		}

	template<class T, class Ch, class Tr = std::char_traits<Ch>>
	struct basic_formatter : boost::noncopyable
	{
	protected:
		typedef std::basic_ostream<Ch, Tr>              ostream_type;
		
		typedef boost::io::basic_ios_all_saver<Ch, Tr>  all_saver_type;
		typedef boost::io::basic_ios_fill_saver<Ch, Tr> fill_saver_type;

		const T& m_value;

		explicit basic_formatter(const T& value) throw()
			: m_value(value)
		{
		}
	};

	struct ios_modifier : boost::noncopyable
	{
		ios_modifier() : m_index(std::ios_base::xalloc())
		{
		}

		int get(std::ios_base& ios) const
		{
			return ios.iword(m_index);
		}

		void set(std::ios_base& ios, int value) const
		{
			ios.iword(m_index) = value;
		}

	protected:

		bool get_bit(std::ios_base& ios, int bitmask) const
		{
			return 0 != (get(ios) & bitmask);
		}

		void set_bit(std::ios_base& ios, int bitmask, bool value) const
		{
			if (value)
			{
				set(ios, get(ios) | bitmask);
			}
			else
			{
				set(ios, get(ios) & ~bitmask);
			}
		}

	private:
		int m_index;
	};

}}